﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using VoteInformationSystem.Models;

namespace VoteInformationSystem.Controllers
{
    public class HomeController : Controller
    {
        readonly IBundestagswahlRepository _bundestagswahlrepository = new NpgsqlBundestagswahlRepository();
        readonly IBundeslandRepository _bundeslandrepository = new NpgsqlBundeslandRepository();
        readonly IWahlkreisRepository _wahlkreisrepository = new NpgsqlWahlkreisRepository();

        /// <summary>
        /// Index page that displays list of elections
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            ViewBag.Bundestagswahlen = _bundestagswahlrepository.GetAll().OrderBy(w => w.Jahr);
            return View();
        }

        /// <summary>
        /// Election main page. Displays list of Länder as well as results on federal level.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public ActionResult Bundestagswahl(int Id)
        {
			ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(Id);
			ViewBag.Laender = _bundeslandrepository.GetByBundestagswahl(Id).OrderBy(l => l.Name);
			return View();
        }

        /// <summary>
        /// Bundesland page. Displays winning parties for Erststimme and Zweitstimme per voting district
        /// and links to individual districts for detail views.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)] // disable caching
        public ActionResult Bundesland(int Id)
        {
			
			ViewBag.Land = _bundeslandrepository.Get(Id);
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(ViewBag.Land.IdBundestagswahl);
			ViewBag.Wahlkreise = _wahlkreisrepository.GetByBundesland(Id).OrderBy(k => k.Nummer);
			return View();
        }

        /// <summary>
        /// Voting district results view. Includes comparison with results from previous election, if applicable
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Wahlkreis(int Id)
        {
			ViewBag.Wahlkreis = _wahlkreisrepository.Get(Id);
            ViewBag.Land = _bundeslandrepository.Get(ViewBag.Wahlkreis.IdBundesland);
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(ViewBag.Land.IdBundestagswahl);
            ViewBag.AlterWahlkreis = _wahlkreisrepository.GetPrevious(ViewBag.Wahlkreis.Id,
                                                                           _bundestagswahlrepository.GetPrevious(
                                                                               ViewBag.Bundestagswahl.Id).Id);
            return View();
        }

        /// <summary>
        /// Q1: Display seats distribution in parliament.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q1(int Id)
        {
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(Id);
            IPlaetzeverteilungBundestagRepository repository = new NpgsqlPlaetzeverteilungBundestagRepository();
            ViewBag.PlaetzeVerteilung = repository.GetPlaetzeVerteilung(ViewBag.Bundestagswahl.Jahr);
            return View();
        }

        /// <summary>
        /// Q2: Display list of elected members of parliament.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q2(int Id)
        {
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(Id);
            IPolitikerBundestagRepository repository = new NpgsqlPolitikerBundestagRepository();
            ViewBag.Politiker = repository.GetPolitiker(ViewBag.Bundestagswahl.Jahr);
            return View();
        }

        /// <summary>
        /// Q3: Display details for voting district.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q3(int Id)
        {
            ViewBag.Wahlkreis = _wahlkreisrepository.Get(Id);
            ViewBag.Land = _bundeslandrepository.Get(ViewBag.Wahlkreis.IdBundesland);
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(ViewBag.Land.IdBundestagswahl);
            Bundestagswahl vorherigeBundestagswahl = _bundestagswahlrepository.GetPrevious(ViewBag.Bundestagswahl.Id);
            ViewBag.AlterWahlkreis = _wahlkreisrepository.GetPrevious(Id, vorherigeBundestagswahl.Id);

            IErststimmenProWahlkreisRepository erststimmenProWahlkreisRepository = new NpgsqlErststimmenProWahlkreisRepository();
            ViewBag.Erststimmen = erststimmenProWahlkreisRepository.GetByWahlkreis(Id, vorherigeBundestagswahl.Id);
            IZweitstimmenProWahlkreisRepository zweitstimmenProWahlkreisRepository = new NpgsqlZweitstimmenProWahlkreisRepository();
            ViewBag.Zweitstimmen = zweitstimmenProWahlkreisRepository.GetByWahlkreis(Id, vorherigeBundestagswahl.Id);
            return View();
        }

        /// <summary>
        /// Q4: Display overview of all voting districts for given Bundesland.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q4(int Id)
        {
            ViewBag.Land = _bundeslandrepository.Get(Id);
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(ViewBag.Land.IdBundestagswahl);
            ViewBag.Wahlkreise = _wahlkreisrepository.GetByBundesland(Id).OrderBy(k => k.Nummer);
            return View();
        }

        /// <summary>
        /// Q5: Display overhang seats in parliament.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q5(int Id)
        {
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(Id);
            IUeberhangmandateProParteiBundeslandRepository ueberhangmandateProParteiBundeslandRepository = new NpgsqlUeberhangmandateProParteiBundeslandRepository();
            ViewBag.Ueberhangmandate = ueberhangmandateProParteiBundeslandRepository.GetUeberhangmandateProParteiBundesland(ViewBag.Bundestagswahl.Jahr);
            return View();
        }

        /// <summary>
        /// Q6: Display closest races per party
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q6(int Id)
        {
            ViewBag.Bundestagswahl = _bundestagswahlrepository.Get(Id);
            IKnappsteAusgaengeRepository knappsteAusgaengeRepository = new NpgsqlKnappsteAusgaengeRepository();
            ViewBag.KnappsteAusgaenge = knappsteAusgaengeRepository.Get(ViewBag.Bundestagswahl.Jahr);
            return View();
        }

        /// <summary>
        /// Q7: Display details for voting district.
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public ActionResult Q7()
        {
            ViewBag.Wahlkreise = _wahlkreisrepository.GetQ7();
            return View();
        }

        /// <summary>
        /// Retrieve data for seats distribution pie chart.
        /// </summary>
        /// <param name="Jahr"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetPieChartData(int Jahr)
        {
            IPlaetzeverteilungBundestagRepository repository = new NpgsqlPlaetzeverteilungBundestagRepository();

            return Json((object)repository.GetPlaetzeVerteilung(Jahr));
        }

        /// <summary>
        /// Retrieve data for table of elected members of parliament.
        /// </summary>
        /// <param name="Jahr"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetPolitikerTableData(int Jahr)
        {
            IPolitikerBundestagRepository repository = new NpgsqlPolitikerBundestagRepository();
            return Json((object)repository.GetPolitiker(Jahr));
        }

        /// <summary>
        /// Retrieve list of federal elections
        /// </summary>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetBundestagswahlen()
        {
            IEnumerable<Bundestagswahl> bundestagswahlen = _bundestagswahlrepository.GetAll();
			return Json(new SelectList(bundestagswahlen, "Id", "Jahr"));      
        }

        /// <summary>
        /// Retrieve list of overhang seats of parliament.
        /// </summary>
        /// <param name="Jahr"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetUeberhangmandate(int Jahr)
        {
            IUeberhangmandateProParteiBundeslandRepository ueberhangmandateProParteiBundeslandRepository = new NpgsqlUeberhangmandateProParteiBundeslandRepository();
            return Json((object)ueberhangmandateProParteiBundeslandRepository.GetUeberhangmandateProParteiBundesland(Jahr));
            return null;
        }

        /// <summary>
        /// Retrieve Zweistimmen list per voting district.
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="IdBundestagswahl"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetZweitstimmenProWahlkreis(int Id, int IdBundestagswahl)
        {
            Bundestagswahl vorherigeBundestagswahl = _bundestagswahlrepository.GetPrevious(IdBundestagswahl);
            IZweitstimmenProWahlkreisRepository zweitstimmenProWahlkreisRepository = new NpgsqlZweitstimmenProWahlkreisRepository();
            return Json((object)zweitstimmenProWahlkreisRepository.GetByWahlkreis(Id, vorherigeBundestagswahl.Id));
        }

        /// <summary>
        /// Retrieve Erststimmen list per voting district.
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="IdBundestagswahl"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetErststimmenProWahlkreis(int Id, int IdBundestagswahl)
        {
            Bundestagswahl vorherigeBundestagswahl = _bundestagswahlrepository.GetPrevious(IdBundestagswahl);
            IErststimmenProWahlkreisRepository erststimmenProWahlkreisRepository = new NpgsqlErststimmenProWahlkreisRepository();
            return Json((object)erststimmenProWahlkreisRepository.GetByWahlkreis(Id, vorherigeBundestagswahl.Id));
        }

        /// <summary>
        /// Get winning direct candidate for a given voting district in the previous general election.
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="IdBundestagswahl"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetDirektkandidatVorperiode(int Id, int IdBundestagswahl)
        {
            Bundestagswahl vorherigeBundestagswahl = _bundestagswahlrepository.GetPrevious(IdBundestagswahl);
            Wahlkreis alterWahlkreis = _wahlkreisrepository.GetPrevious(Id, vorherigeBundestagswahl.Id);
            return Json((object)alterWahlkreis);
        }

        /// <summary>
        /// Get closest races information
        /// </summary>
        /// <param name="Jahr"></param>
        /// <returns></returns>
        [OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
        public JsonResult GetKnappsteAusgaenge(int Jahr)
        {
            IKnappsteAusgaengeRepository knappsteAusgaengeRepository = new NpgsqlKnappsteAusgaengeRepository();
            return Json((object) knappsteAusgaengeRepository.Get(Jahr));
        }
    }
}
